#include <iostream>
#include <thread>
#include <list>
#include <mutex>
using namespace std;

/*
P9 
一.设计模式 
    单例模式 

二.单例设计模式共享数据问题分析
    面临的问题，我们需要在子线程里面创建单例类
    我们需要面临成员函数getInstance()互斥

三.std::call_once() 
    能够保证 函数A 自被调用一次
    该函数的第二个参数是函数名
    具备互斥量这种能力，而且效率上，比互斥量消耗的资源更少
    call_once() 需要与一个标记结合使用，这个标记std::once_flag (一个结构)
*/

mutex mymutex;

class SingleTon
{
private:
    SingleTon() {}

    static SingleTon * myInstance; //静态成员变量

public:
    static SingleTon *  getInstance()
    {
        // if(myInstance != 0) 条件成立 ，则肯定表示myInstance 已经被new过
        // if(myInstance == 0) // 不代表myInstance没被new过

        if(myInstance == 0) //双重锁定 双重检查
        {
            unique_lock<mutex> uniqueLock(mymutex); // 自动加锁
            if(myInstance == 0)
            {
                //_sleep(2);
                myInstance = new SingleTon();
                static GarbageCollection gc;
            }
        }
        return myInstance;
    }

    class GarbageCollection  //类中类， 用于释放对象
    {
        public:
        ~GarbageCollection()
        {
            if(myInstance)
            {
                delete myInstance;
                myInstance = nullptr;
                cout<<"gc"<<endl;
            }
        }
    };
    void func()
    {
        cout<<"对象地址:"<<myInstance<<endl;
    }

};
SingleTon * SingleTon::myInstance = nullptr;

void mythreadEnter()
{
    cout<<"我的线程开始执行"<<endl;
    SingleTon* p = SingleTon::getInstance();
    p->func();

}

int main()
{
    //SingleTon a1,a2;
    thread myObj1(mythreadEnter);
    thread myObj2(mythreadEnter);
    thread myObj3(mythreadEnter);

    SingleTon* p1 = SingleTon::getInstance();
    SingleTon* p2 = SingleTon::getInstance();
    p1->func();
    p2->func();

    myObj1.join();
    myObj2.join();
    myObj3.join();
}